#include "./ctrl.h"
#include "../xlib/gpio.h"

namespace heat_driver {

Ctrl ctrl;

namespace ctrl_impl {

using namespace stm32f1;

using STEAM_HEAT = gpio::PB<0>;
using WATER_HEAT = gpio::PB<9>;

using V3 = gpio::PB<10>;
using V4 = gpio::PB<11>;
using DRAW_PUMP = gpio::PB<12>;
using WATER_PUMP = gpio::PB<13>;
using V6 = gpio::PB<14>;
using STEAM_PUMP = gpio::PB<15>;
using V_EXIT_RO = gpio::PC<8>;
using P2 = gpio::PC<9>;
using P1 = gpio::PC<10>;
using V_ENTER_RO = gpio::PC<11>;
using V1 = gpio::PC<12>;
using V2 = gpio::PC<13>;
using V5 = gpio::PC<14>;
using V_DROP = gpio::PC<15>;

}

using namespace ctrl_impl;

void Ctrl::init() {
    rcc::enable<
        STEAM_HEAT, WATER_HEAT,
        V3, V4, DRAW_PUMP, WATER_PUMP, V6, STEAM_PUMP, 
        V_EXIT_RO, P2, P1, V_ENTER_RO, V1, V2, V5, V_DROP
    >();
    gpio::config<
        gpio::Cfg<STEAM_HEAT, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<WATER_HEAT, gpio::Mode::OUT_50MHz_PP>,

        gpio::Cfg<V3, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V4, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<DRAW_PUMP, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<WATER_PUMP, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V6, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<STEAM_PUMP, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V_EXIT_RO, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<P2, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<P1, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V_ENTER_RO, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V1, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V2, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V5, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<V_DROP, gpio::Mode::OUT_50MHz_PP>
    >();
    close(Parts::STEAM_HEAT);
    close(Parts::WATER_HEAT);
    close(Parts::V3);
    close(Parts::V4);
    close(Parts::DRAW_PUMP);
    close(Parts::WATER_PUMP);
    close(Parts::V6);
    close(Parts::STEAM_PUMP);
    close(Parts::V_EXIT_RO);
    close(Parts::P2);
    close(Parts::P1);
    close(Parts::V_ENTER_RO);
    close(Parts::V1);
    close(Parts::V2);
    close(Parts::V5);
    close(Parts::V_DROP);
}

static bool partsFlags[16];

uint16_t Ctrl::flags() const {
    uint16_t value = 0; 
    for (uint8_t i = 0; i < 16; i ++) {
        value |= (partsFlags[i] << i);
    }
    return value;
}

void Ctrl::open(Parts parts) {

    switch (parts) {
        case Parts::STEAM_HEAT: STEAM_HEAT::set(); break;
        case Parts::WATER_HEAT: WATER_HEAT::set(); break;
        case Parts::V3: V3::set(); break;
        case Parts::V4: V4::set(); break;
        case Parts::DRAW_PUMP: DRAW_PUMP::set(); break;
        case Parts::WATER_PUMP: WATER_PUMP::set(); break;
        case Parts::V6: V6::set(); break;
        case Parts::STEAM_PUMP: STEAM_PUMP::set(); break;
        case Parts::V_EXIT_RO: V_EXIT_RO::set(); break;
        case Parts::P2: P2::set(); break;
        case Parts::P1: P1::set(); break;
        case Parts::V_ENTER_RO: V_ENTER_RO::set(); break;
        case Parts::V1: V1::set(); break;
        case Parts::V2: V2::set(); break;
        case Parts::V5: V5::set(); break;
        case Parts::V_DROP: V_DROP::set(); break;
        default: return;
    }
    partsFlags[ static_cast<uint8_t>(parts) ] = true;
}

void Ctrl::close(Parts parts) {

    switch (parts) {
        case Parts::STEAM_HEAT: STEAM_HEAT::clr(); break;
        case Parts::WATER_HEAT: WATER_HEAT::clr(); break;
        case Parts::V3: V3::clr(); break;
        case Parts::V4: V4::clr(); break;
        case Parts::DRAW_PUMP: DRAW_PUMP::clr(); break;
        case Parts::WATER_PUMP: WATER_PUMP::clr(); break;
        case Parts::V6: V6::clr(); break;
        case Parts::STEAM_PUMP: STEAM_PUMP::clr(); break;
        case Parts::V_EXIT_RO: V_EXIT_RO::clr(); break;
        case Parts::P2: P2::clr(); break;
        case Parts::P1: P1::clr(); break;
        case Parts::V_ENTER_RO: V_ENTER_RO::clr(); break;
        case Parts::V1: V1::clr(); break;
        case Parts::V2: V2::clr(); break;
        case Parts::V5: V5::clr(); break;
        case Parts::V_DROP: V_DROP::clr(); break;
        default: return;
    }
    partsFlags[ static_cast<uint8_t>(parts) ] = false;
}

}
